 package srdb.migration.common;
 
   
 import java.io.InputStream;
 import java.io.PipedOutputStream;
 import java.math.BigDecimal;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.sql.Time;
import java.sql.Timestamp;

import srdb.migration.MigrationToolkit;
import srdb.migration.dbhandler.enterprisedb.RedwoodBridge;
import srdb.migration.schema.metadata.Column;
import srdb.migration.schema.metadata.ColumnList;
import srdb.migration.schema.metadata.LargeBufferInputStream;
import srdb.migration.schema.metadata.Table;
import srdb.migration.schema.metadata.Column.DataType;
 
 public abstract class MTKData
 {
   protected static final String DBLINK_ORA_CONN_NAME = "mtk_connection";
   protected static int MaxBufferSize = 8388608;//mod by kevin 2015年05月07日 default:8388608/8M now:512m
   protected Connection dbConn = null;
   protected Statement stmt = null;
   protected ResultSet rs = null;
   protected boolean hasMoreData = false;
   protected String lastTable = "";
   protected PreparedStatement dblinkOraCopyStmt = null;
 
   protected String sourceDBNamedCharSet = "UTF-8";
 
   boolean defaultAutoCommitMode = true;
 
   public abstract void setTableData(String paramString, InputStream paramInputStream, char paramChar)
     throws Exception;
 
   public abstract int setTableDataViaDBLinkOra(String paramString1, String paramString2, String paramString3, boolean paramBoolean)
     throws SQLException;
 
   public void commit()
     throws SQLException
   {
     if (!this.dbConn.getAutoCommit())
       this.dbConn.commit();
   }
 
   public void rollback()
     throws SQLException
   {
     if (!this.dbConn.getAutoCommit())
       this.dbConn.rollback();
   }
 
   public void setLastTable(String lastTable)
   {
     this.lastTable = lastTable;
   }
 
   public void reset() {
     this.hasMoreData = false;
     try {
       this.rs.close();
       this.stmt.close();
       this.rs = null;
       this.stmt = null;
     }
     catch (Exception ex)
     {
     }
   }
 
   public LargeBufferInputStream getTableData(MTKConstants.DATABASE_TYPE sourceDBType, MTKConstants.DATABASE_TYPE targetDBType, Table table, char copyDelimeter, boolean escapeTabDelimiter) throws Exception {
     LargeBufferInputStream pis = new LargeBufferInputStream(MaxBufferSize);
     PipedOutputStream pos = new PipedOutputStream();
     String newLineSequence = "\\\\n";
     String carriageReturnSequence = "\\\\r";
     String columnTabDelimiter = "\\\\t";
     //管道链接
     pis.connect(pos);
     try
     {
       if (!this.hasMoreData) {
         if (this.lastTable.compareToIgnoreCase(table.getFullName()) != 0) {
           this.stmt = this.dbConn.createStatement();
 
           if ((sourceDBType == MTKConstants.DATABASE_TYPE.SRDB) || (sourceDBType == MTKConstants.DATABASE_TYPE.ENTERPRISEDB))
           {
             this.defaultAutoCommitMode = this.dbConn.getAutoCommit();
             this.dbConn.setAutoCommit(false);
 
             this.stmt.setFetchSize(100);//mod by kevin 2015年05月07日 default 100
           }
 
           this.rs = this.stmt.executeQuery(sourceDBType == MTKConstants.DATABASE_TYPE.ORACLE ? table.getSelectSQL(sourceDBType) : table.getSelectSQL());
//           System.out.println(table.getSelectSQL(sourceDBType));
           this.lastTable = table.getFullName();
         } else {
           return null;
         }
       }
 
       while (this.rs.next()) {
    	   //数据移植
         for (int i = 0; i < table.getColumns().size(); i++) {
           String lastField = null;
           boolean largeObjFlag = false;
           Column column = table.getColumns().get(i);
//           1.$SwitchMap$com$edb$schema$metadata$Column$DataType[column.getDataType().ordinal()]
           switch (Column.DataType.values()[column.getDataType().ordinal()]) {
           case INTEGER://int 
             if (this.rs.getObject(i + 1) == null) break;
             lastField = String.valueOf(this.rs.getInt(i + 1)); break;
           case VARCHAR:
           case NVARCHAR:
           case TEXT:
           case XML:
           case BITSTRING:
           case USERDEFINED:
             lastField = this.rs.getString(i + 1);
             if (lastField == null)
               break;
             if (MigrationToolkit.replaceNullChar()) {
               lastField = lastField.replaceAll("", String.valueOf(MigrationToolkit.nullReplacementChar()));
             }
             else {
               lastField = lastField.replaceAll("", "");
             }
 
             lastField = lastField.replace("\\", "\\\\");
 
             lastField = lastField.replaceAll("\n", newLineSequence);
             lastField = lastField.replaceAll("\r", carriageReturnSequence);
 
             if ((escapeTabDelimiter) && (copyDelimeter == '\t')) {
               lastField = lastField.replaceAll("\t", columnTabDelimiter);
             }
 
             if ((sourceDBType != MTKConstants.DATABASE_TYPE.SRDB) && (sourceDBType != MTKConstants.DATABASE_TYPE.ENTERPRISEDB))
               break;
             if ((!column.getDataTypeString().equalsIgnoreCase("TEXT")) && (!column.getDataTypeString().equalsIgnoreCase("XML"))) break;
             table.setPgTextColSize(lastField.length()); break;
           case MONEY:
             if (this.rs.getObject(i + 1) == null) break;
             lastField = new Double(this.rs.getDouble(i + 1)).toString(); break;
           case FLOAT:
           case NUMERIC:
           case BINARY_FLOAT:
           case BIT:
             if (this.rs.getObject(i + 1) == null) break;
             if ((column.isReal()) || (column.isBinaryFloat()))
               lastField = new Float(this.rs.getFloat(i + 1)).toString();
             else if (column.isDouble())
               lastField = new Double(this.rs.getDouble(i + 1)).toString();
             else
               lastField = this.rs.getBigDecimal(i + 1).toString(); break;
           case TIME:
             if (this.rs.getTime(i + 1) == null) break;
             if (((sourceDBType == MTKConstants.DATABASE_TYPE.SRDB) || (sourceDBType == MTKConstants.DATABASE_TYPE.ENTERPRISEDB)) && ((targetDBType == MTKConstants.DATABASE_TYPE.SRDB) || (targetDBType == MTKConstants.DATABASE_TYPE.ENTERPRISEDB)))
             {
               lastField = this.rs.getString(i + 1);
             }
             else lastField = this.rs.getTime(i + 1).toString(); break;
           case TIMESTAMP:
             if (this.rs.getTimestamp(i + 1) == null) break;
             lastField = this.rs.getTimestamp(i + 1).toString(); break;
           case DATE:
             if (this.rs.getTimestamp(i + 1) == null)
             {
               break;
             }
 
             if (((sourceDBType == MTKConstants.DATABASE_TYPE.SRDB) || (sourceDBType == MTKConstants.DATABASE_TYPE.ENTERPRISEDB)) && ((targetDBType == MTKConstants.DATABASE_TYPE.SRDB) || (targetDBType == MTKConstants.DATABASE_TYPE.ENTERPRISEDB)))
             {
               lastField = this.rs.getString(i + 1);
             }
             else lastField = this.rs.getTimestamp(i + 1).toString(); break;
           case BYTEA:
             largeObjFlag = true;
             break;
           case INTERVAL:
             if (this.rs.getString(i + 1) == null) break;
             if ((sourceDBType == MTKConstants.DATABASE_TYPE.ORACLE) && ((targetDBType == MTKConstants.DATABASE_TYPE.ENTERPRISEDB) || (targetDBType == MTKConstants.DATABASE_TYPE.SRDB)))
             {
               lastField = RedwoodBridge.getPGIntervalString(this.rs.getString(i + 1));
             }
             else lastField = this.rs.getString(i + 1); break;
           case BOOLEAN:
             lastField = String.valueOf(this.rs.getBoolean(i + 1));
             break;
           case GEOMETRIC:
             lastField = this.rs.getString(i + 1);
             break;
           case ARRAY:
             if (this.rs.getArray(i + 1) == null) break;
             lastField = this.rs.getArray(i + 1).toString(); break;
           case NAME:
           case OID:
           case NETWORKADDRESS:
//             lastField = this.rs.getString(i + 1);
//             break;
//           case BYTEA:
           case OTHER:
             lastField = this.rs.getString(i + 1);
             break;
           default:
             if ((this.rs.getMetaData().getColumnTypeName(i + 1).equalsIgnoreCase("CLOB")) || (this.rs.getMetaData().getColumnTypeName(i + 1).equalsIgnoreCase("NCLOB")))
             {
               throw new Exception("This Table Contains CLOB data, Marked for Bulk Insert Loading");
             }if ((this.rs.getMetaData().getColumnType(i + 1) == 2002) && (!column.getDataTypeString().equalsIgnoreCase("SDO_GEOMETRY")))
             {
               lastField = RedwoodBridge.convertToPGObjectTypeFormat(this.rs.getObject(i + 1));
             }
             else if (column.getDataTypeString().equalsIgnoreCase("SDO_GEOMETRY"))
               lastField = null;
             else {
               throw new Exception(this.rs.getMetaData().getColumnTypeName(i + 1) + " is Not Supported by COPY");
             }
 
           }
 
           if ((this.rs.wasNull()) || (largeObjFlag) || (lastField == null)) {
             if (targetDBType != MTKConstants.DATABASE_TYPE.NPS) {
               pos.write(new String("\\N").getBytes());
             }
 
           }
           else if (column.getDataType() == Column.DataType.NVARCHAR)
             pos.write(lastField.getBytes("UTF-8"));
           else {
             pos.write(lastField.getBytes(this.sourceDBNamedCharSet));
           }
 
           if (i < table.getColumns().size() - 1) {
             pos.write(copyDelimeter);
           }
         }
 
         pos.write(10);
 
         pis.addRowNum();
 
         if (MaxBufferSize - pis.getLength() < table.getMaxRowSize()) {
           pos.flush();
           pos.close();
           this.hasMoreData = true;
           return pis;
         }
 
       }
 
       this.rs.close();
       this.stmt.close();
       this.hasMoreData = false;
 
       if ((sourceDBType == MTKConstants.DATABASE_TYPE.SRDB) || (sourceDBType == MTKConstants.DATABASE_TYPE.ENTERPRISEDB))
       {
         if (this.dbConn != null) {
           this.dbConn.setAutoCommit(this.defaultAutoCommitMode);
         }
       }
 
       pos.flush();
       pos.close();
     }
     catch (Exception ex)
     {
       if (this.rs != null) {
         this.rs.close();
       }
 
       if (this.stmt != null) {
         this.stmt.close();
       }
 
       if ((sourceDBType == MTKConstants.DATABASE_TYPE.SRDB) || (sourceDBType == MTKConstants.DATABASE_TYPE.ENTERPRISEDB))
       {
         if (this.dbConn != null) {
           this.dbConn.setAutoCommit(this.defaultAutoCommitMode);
         }
       }
 
       throw ex;
     }
 
     return pis;
   }
 }

/* 

 * 
 */